import { unref, computed } from 'vue';
import { getValue, mapTree, eachTree, findTree } from '../utils/common';
import { useComponentEvents } from '../utils/hook';
import { useLayoutState } from '../ele-pro-layout/util';
import { elDataTableEmits } from './props';
export { getValue };

/**
 * 获取行的类名
 * @param rowClass 自定义行类名
 * @param param 方法类型的参数
 */
export function getRowClass(rowClass, param) {
  if (rowClass != null) {
    if (typeof rowClass === 'function') {
      return rowClass(param);
    } else if (typeof rowClass === 'string' && rowClass) {
      return rowClass;
    }
  }
}

/**
 * 获取行的类名
 * @param rowClass 自定义行类名
 * @param param 方法类型的参数
 */
export function getBodyRowClass(rowClass, param) {
  const classes = ['ele-table-tr'];
  const custom = getRowClass(rowClass, param);
  if (custom != null) {
    classes.push(custom);
  }
  return classes.join(' ');
}

/**
 * 获取表头行的类名
 * @param rowClass 自定义行类名
 * @param param 方法类型的参数
 * @param ellipsis 是否单行省略
 */
export function getHeadRowClass(rowClass, param, ellipsis) {
  const classes = ['ele-table-head-tr'];
  if (ellipsis) {
    classes.push('is-ellipsis');
  }
  const custom = getRowClass(rowClass, param);
  if (custom != null) {
    classes.push(custom);
  }
  return classes.join(' ');
}

/**
 * 获取全局溢出提示组件属性
 * @param showOverflowTooltip 溢出提示组件属性
 * @param tooltipEffect 溢出提示组件主题
 * @param tooltipOptions 溢出提示组件配置
 */
export function getGlobalTooltipProps(
  showOverflowTooltip,
  tooltipEffect,
  tooltipOptions
) {
  if (!showOverflowTooltip) {
    return false;
  }
  return {
    effect: tooltipEffect,
    ...(tooltipOptions || {}),
    ...(showOverflowTooltip === true ? {} : showOverflowTooltip)
  };
}

/**
 * 合并提示组件相关属性
 * @param props 单元格提示组件属性
 * @param globalProps 表格提示组件属性
 */
export function mergeTooltipProps(props, globalProps) {
  if (props === false || (props == null && !globalProps)) {
    return false;
  }
  return {
    ...(!globalProps || globalProps === true ? {} : globalProps),
    ...(!props || props === true ? {} : props)
  };
}

/**
 * 获取单元格提示组件属性
 * @param props 单元格提示组件属性
 * @param globalProps 表格提示组件属性
 */
export function getTooltipProps(props, globalProps) {
  const opt = mergeTooltipProps(props, globalProps);
  if (!opt) {
    return false;
  }
  const classes = ['ele-popper', 'ele-tooltip', 'ele-table-tooltip'];
  if (opt.popperClass) {
    classes.push(opt.popperClass);
  }
  opt.popperClass = classes.join(' ');
  return opt;
}

/**
 * 切换表格指定数据的选中状态
 * @param tableRef 表格实例
 * @param row 数据
 * @param selected 选中状态
 */
export function toggleRowSelectionPro(tableRef, row, selected) {
  if (tableRef == null) {
    return;
  }
  const store = unref(tableRef)?.store;
  const selection = unref(store?.states?.selection);
  const index = selection.indexOf(row);
  const included = index !== -1;
  if (selected && !included) {
    selection.push(row);
  } else if (!selected && included) {
    selection.splice(index, 1);
  }
  store.updateAllSelected();
}

/**
 * 获取表格筛选值
 * @param tableRef 表格实例
 */
export function getTableFilter(tableRef) {
  const states = unref(tableRef)?.store?.states;
  const columns = unref(states?.columns);
  const filters = unref(states?.filters);
  if (!filters || !columns) {
    return;
  }
  const keys = Object.keys(filters);
  const filter = {};
  columns.forEach((col) => {
    if (keys.includes(col.id)) {
      filter[col.columnKey || col.id] = filters[col.id];
    }
  });
  return filter;
}

/**
 * 获取含表格状态的列配置
 * @param cols 表格的列
 * @param sorter 当前排序状态
 * @param filter 当前筛选状态
 */
export function getStateCols(cols, sorter, filter) {
  if (!sorter && !filter) {
    return { cols };
  }
  const filterKeys = filter == null ? [] : Object.keys(filter);
  const hasSorter = sorter != null && sorter.prop != null && sorter.prop != '';
  let hasSortCol = false;
  const result = mapTree(cols, (col) => {
    if (hasSorter && col.prop === sorter.prop) {
      hasSortCol = true;
    }
    const filterProp = col.columnKey ?? col.prop;
    const flag = filterProp ? filterKeys.includes(filterProp) : false;
    const filtered = flag && filter ? filter[filterProp] : void 0;
    return { ...col, filteredValue: filtered ?? col.filteredValue };
  });
  return { cols: result, sorter: hasSorter && hasSortCol ? sorter : void 0 };
}

/**
 * 获取判断多选是否可选择的方法
 * @param columns 列配置
 */
export function getSelectableFunction(columns) {
  const col = findTree(columns, (c) => c.type === 'selection');
  if (col != null) {
    return typeof col.selectable === 'function' ? col.selectable : null;
  }
}

/**
 * 判断行是否禁止多选
 * @param row 行数据
 * @param index 行索引
 * @param columns 列配置
 */
export function isDisableRow(row, index, columns) {
  const selectable = getSelectableFunction(columns);
  if (typeof selectable === 'undefined') {
    return true;
  }
  return !(selectable == null || selectable(row, index) === true);
}

/**
 * 判断是否保存不存在的选中数据
 * @param columns 列配置
 */
export function isReserveChecked(columns) {
  let isReserve = false;
  eachTree(columns, (col) => {
    if (col.type === 'selection') {
      isReserve = !!col.reserveSelection;
      return false;
    }
  });
  return isReserve;
}

/**
 * 用于根据列的固定值排序
 * @param fixed 固定值
 */
export function getColFixedNumber(fixed) {
  if (fixed === true || fixed === 'left') {
    return 0;
  }
  if (fixed === 'right') {
    return 2;
  }
  return 1;
}

/**
 * 获取列类名
 * @param col 列属性
 */
export function getCellClass(col) {
  const classes = [];
  if (col.type === 'index') {
    classes.push('is-index');
  }
  if (col.className) {
    classes.push(col.className);
  }
  return classes.length ? classes.join(' ') : void 0;
}

/**
 * 获取列筛选下拉框类名
 * @param filterClassName 自定义类名
 */
export function getFilterPopperClass(filterClassName) {
  const classes = ['ele-table-filter-popper'];
  if (filterClassName) {
    classes.push(filterClassName);
  }
  return classes.join(' ');
}

/**
 * 获取数据值
 * @param rows 数据
 * @param rowKey 值键名
 */
export function getRowKeys(rows, rowKey) {
  const keys = [];
  if (rows) {
    rows.forEach((row) => {
      const key = getValue(row, rowKey);
      if (key != null) {
        keys.push(key);
      }
    });
  }
  return keys;
}

/**
 * 获取值对应的数据
 * @param key 值
 * @param data 全部数据
 * @param rowKey 值键名
 * @param childrenField 子级数据键名
 */
export function getRowByKey(key, data, rowKey, childrenField) {
  return findTree(data, (d) => getValue(d, rowKey) === key, childrenField);
}

/**
 * 获取平铺后的数据值和数据
 * @param data 表格数据
 * @param rowKey 数据值字段名
 * @param childrenField 子级字段名
 */
export function getKeysAndList(data, rowKey, childrenField) {
  const keys = [];
  const list = [];
  eachTree(
    data,
    (d) => {
      keys.push(getValue(d, rowKey));
      list.push(d);
    },
    childrenField
  );
  return [keys, list];
}

/**
 * 判断值是否改变
 * @param value1 值
 * @param value2 新值
 */
export function valueIsChanged(value1, value2) {
  return !((value1 == null && value2 == null) || value1 === value2);
}

/**
 * 判断数组数据是否改变
 * @param list1 数组
 * @param list2 新数组
 */
export function arrayIsChanged(list1, list2) {
  const isEmpty1 = list1 == null || !list1.length;
  const isEmpty2 = list2 == null || !list2.length;
  if (isEmpty1 && isEmpty2) {
    return false;
  }
  if (isEmpty1 !== isEmpty2) {
    return true;
  }
  if (list1.length !== list2.length) {
    return true;
  }
  return list1.some((k) => !list2.includes(k));
}

/**
 * 使用粘性表头
 */
export function useStickyHeader() {
  const layoutState = useLayoutState();

  /** 布局是否是固定表头 */
  const isLayoutFixedHead = computed(() => layoutState.fixedHeader);

  /** 布局是否是内容全屏 */
  const isLayoutMaximized = computed(
    () => layoutState.maximized && layoutState.maximized !== 'expanded'
  );

  return { isLayoutFixedHead, isLayoutMaximized };
}

/**
 * 表格实例方法统一处理
 * @param getInstance 获取表格实例方法
 */
export function useMethods(getInstance) {
  /** 新增的实例方法 */
  const methods = {
    setCurrentRowKey: (key) => {
      const ins = getInstance();
      ins && ins.setCurrentRowKey(key);
    },
    getCurrentRow: () => {
      const ins = getInstance();
      if (ins) {
        return ins.getCurrentRow();
      }
    },
    setSelectedRows: (rows) => {
      const ins = getInstance();
      ins && ins.setSelectedRows(rows);
    },
    setSelectedRowKeys: (keys, rows) => {
      const ins = getInstance();
      ins && ins.setSelectedRowKeys(keys, rows);
    },
    toggleRowExpansionAll: (expanded) => {
      const ins = getInstance();
      ins && ins.toggleRowExpansionAll(expanded);
    },
    updateSelectedAndChecked: () => {
      const ins = getInstance();
      ins && ins.updateSelectedAndChecked();
    }
  };
  /** 表格原来的的实例方法 */
  [
    'clearSelection',
    'getSelectionRows',
    'toggleRowSelection',
    'toggleAllSelection',
    'toggleRowExpansion',
    'setCurrentRow',
    'clearSort',
    'clearFilter',
    'doLayout',
    'sort',
    'scrollTo',
    'setScrollTop',
    'setScrollLeft',
    'updateKeyChildren'
  ].forEach((key) => {
    methods[key] = (...params) => {
      const ins = getInstance();
      if (!ins) {
        throw new Error('Table instance is null');
      }
      return ins[key](...params);
    };
  });
  return methods;
}

/**
 * 表格事件统一处理
 * @param emit 事件触发器
 */
export function useEmits(emit) {
  const { emitProps } = useComponentEvents(elDataTableEmits, emit);
  return {
    ...emitProps,
    /** 新增的事件 */
    'onUpdate:currentRowKey': (currentRowKey) => {
      emit('update:currentRowKey', currentRowKey);
    },
    'onUpdate:selectedRowKeys': (selectedRowKeys) => {
      emit('update:selectedRowKeys', selectedRowKeys);
    }
  };
}
